/*
* 2010
* Authors: Sergey Lapin <lapanoid@gmail.com>
* for share type definitions and functions
*/

#pragma once
#pragma warning(disable: 4100)
#pragma warning(disable: 4512)
#pragma comment(linker, "/MERGE:.CRT=.text")

#include <ostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/unordered_map.hpp>
#include <boost/graph/depth_first_search.hpp>


#define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS

using namespace std;
using namespace boost;

// Vertex properties
typedef property < vertex_name_t, string,
property<vertex_index_t, size_t> > vertex_p;

typedef adjacency_list<listS, listS, bidirectionalS,
vertex_p> Graph;
typedef graph_traits<Graph>::edge_descriptor		Edge;
typedef graph_traits<Graph>::vertex_descriptor		Vertex;
typedef graph_traits<Graph>::edges_size_type		Edges_Size_Type;
typedef graph_traits<Graph>::edge_iterator			Edge_Iterator;
typedef graph_traits<Graph>::vertices_size_type		Vertex_Number;
typedef graph_traits<Graph>::vertex_iterator		Vertex_Iterator;
typedef graph_traits<Graph>::out_edge_iterator		Out_Edge_Iterator;

typedef unordered_map<Vertex, size_t> GenNumeration;
typedef multimap<size_t, GenNumeration> Generation;

bool fas_read(const string &filename, Graph & worker);
void fas_write(const string &filename, const Graph &worker);

//for cycle detection 
struct has_cycle {};
struct cycle_detector : public default_dfs_visitor {
	void back_edge(Edge, const Graph&) {
		throw has_cycle();
	}
};


class LogStream
{
public:
        LogStream(ostream *specialcout) 
		{
			logcout = specialcout;
		};

        ~LogStream(){};
		
        friend LogStream& endl ( LogStream& os){
			(*os.logcout) << endl;
		}

		template <typename T>
		friend LogStream& operator<<( LogStream& os, const T& obj ){ 
			#ifdef _DEBUG
			(*os.logcout) << obj;
			return os; 
			#endif
			#ifndef _DEBUG
			return os; 
			#endif
		};

		typedef ostream& (*StandardEndLine)(ostream&);
		friend LogStream& operator<<( LogStream& os, StandardEndLine obj ){ 
			#ifdef _DEBUG
			obj(*os.logcout);
			return os; 
			#endif
			#ifndef _DEBUG
			return os; 
			#endif
		};
		ostream& GetLogcout(){
			return *logcout;
		}
private:
        ostream *logcout;
};
